Welcome to Xceed DataGrid for Silverlight > Additional Resources > RatingCellEditor Class |
Imports System.Windows Imports System.Windows.Controls Imports Xceed.Silverlight.DataGrid Imports System Imports System.Windows.Input Imports System.Windows.Media.Imaging Namespace Xceed.Silverlight.Documentation <TemplatePart( Name = "ImagesPanel", Type = GetType( Panel ) )>_ Public Class RatingCellEditor Inherits Control Public Sub New() MyBase.New() Me.DefaultStyleKey = GetType( RatingCellEditor ) End Sub Public Shared ReadOnly ContentProperty As DependencyProperty = DependencyProperty.Register("Content", GetType(Object), GetType(RatingCellEditor), New PropertyMetadata(Nothing, New PropertyChangedCallback(RatingCellEditor.OnContentChanged))) Public Property Content() As Object Get Return Me.GetValue(RatingCellEditor.ContentProperty) End Get Set Me.SetValue(RatingCellEditor.ContentProperty, value) End Set End Property Private Shared Sub OnContentChanged(sender As DependencyObject, e As DependencyPropertyChangedEventArgs) Dim source As RatingCellEditor = TryCast(sender, RatingCellEditor) If source Is Nothing Then Return End If source.UpdateImages() End Sub Public Overrides Sub OnApplyTemplate() MyBase.OnApplyTemplate() If Not m_imagesPanel Is Nothing Then Dim image As Image For Each image In m_imagesPanel.Children RemoveHandler image.MouseLeftButtonDown, AddressOf OnImageMouseLeftButtonDown Next image m_imagesPanel.Children.Clear() End If m_imagesPanel = CType( Me.GetTemplateChild( "ImagesPanel" ), Panel ) Me.UpdateImages() End Sub Protected Overrides Function MeasureOverride( ByVal availableSize As Size) As Size Me.UpdateImages() Return MyBase.MeasureOverride( availableSize ) End Function Private Sub UpdateImages() If m_imagesPanel Is Nothing Then Return End If Dim value As Integer = 0 Try value = Convert.ToInt32( Me.Content ) Catch( exception As InvalidCastException ) 'suppress End Try If value <> m_previousValue Then 'Clear the previous images and unregister from MouseDown. Dim image as Image For Each image in m_imagesPanel.Children RemoveHandler image.MouseLeftButtonDown, AddressOf OnImageMouseLeftButtonDown Next image m_imagesPanel.Children.Clear() Dim i As Integer For i = 0 To i < 5 Dim image As New Image() If i < value Then image.Source = RatingCellEditor.FullImage Else image.Source = RatingCellEditor.EmptyImage End If AddHandler image.MouseLeftButtonDown, AddressOf New MouseButtonEventHandler( Me.OnImageMouseLeftButtonDown ) m_imagesPanel.Children.Add( image ) Next i m_previousValue = value End If End Sub Private Sub OnImageMouseLeftButtonDown( ByVal sender As Object, ByVal e As MouseButtonEventArgs ) ME.Content = m_imagesPanel.Children.IndexOf( CType( sender, Image ) ) + 1 End Sub Private m_imagesPanel As Panel Private m_previousValue As Integer = int.MinValue Private Static FullImage As New BitmapImage( New Uri( "Images/star.png", UriKind.Relative ) ) Private Static EmptyImage As New BitmapImage( New Uri( "Images/emptystar.png", UriKind.Relative ) ) End Class End Namespace
using System.Windows; using System.Windows.Controls; using Xceed.Silverlight.DataGrid; using System; using System.Windows.Input; using System.Windows.Media.Imaging; namespace Xceed.Silverlight.Documentation { [TemplatePart( Name = "ImagesPanel", Type = typeof( Panel ) )] public class RatingCellEditor : Control { public RatingCellEditor() : base() { this.DefaultStyleKey = typeof( RatingCellEditor ); } public static readonly DependencyProperty ContentProperty = DependencyProperty.Register( "Content", typeof( object ), typeof( RatingCellEditor ), new PropertyMetadata( null, new PropertyChangedCallback( RatingCellEditor.OnContentChanged ) ) ); public object Content { get { return this.GetValue( RatingCellEditor.ContentProperty ); } set { this.SetValue( RatingCellEditor.ContentProperty, value ); } } private static void OnContentChanged( DependencyObject sender, DependencyPropertyChangedEventArgs e ) { RatingCellEditor source = sender as RatingCellEditor; if( source == null ) return; source.UpdateImages(); } public override void OnApplyTemplate() { base.OnApplyTemplate(); if( m_imagesPanel != null ) { foreach( Image image in m_imagesPanel.Children ) { image.MouseLeftButtonDown -= OnImageMouseLeftButtonDown; } m_imagesPanel.Children.Clear(); } m_imagesPanel = this.GetTemplateChild( "ImagesPanel" ) as Panel; this.UpdateImages(); } protected override Size MeasureOverride( Size availableSize ) { this.UpdateImages(); return base.MeasureOverride( availableSize ); } private void UpdateImages() { if( m_imagesPanel == null ) return; int value = 0; try { value = Convert.ToInt32( this.Content ); } catch( InvalidCastException ) { //suppress } if( value != m_previousValue ) { //Clear the previous images and unregister from MouseDown. foreach( Image image in m_imagesPanel.Children ) { image.MouseLeftButtonDown -= OnImageMouseLeftButtonDown; } m_imagesPanel.Children.Clear(); for( int i = 0; i < 5; i++ ) { Image image = new Image(); if( i < value ) { image.Source = RatingCellEditor.FullImage; } else { image.Source = RatingCellEditor.EmptyImage; } image.MouseLeftButtonDown += new MouseButtonEventHandler( this.OnImageMouseLeftButtonDown ); m_imagesPanel.Children.Add( image ); } m_previousValue = value; } } private void OnImageMouseLeftButtonDown( object sender, MouseButtonEventArgs e ) { this.Content = m_imagesPanel.Children.IndexOf( sender as Image ) + 1; } private Panel m_imagesPanel; private int m_previousValue = int.MinValue; private static BitmapImage FullImage = new BitmapImage( new Uri( "Images/star.png", UriKind.Relative ) ); private static BitmapImage EmptyImage = new BitmapImage( new Uri( "Images/emptystar.png", UriKind.Relative ) ); } }
The following code demonstrates how to use the RatingCellEditor to edit the content of a cell.
<Style TargetType="local:RatingCellEditor"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="local:RatingCellEditor"> <StackPanel x:Name="ImagesPanel" Orientation="Horizontal" /> </ControlTemplate> </Setter.Value> </Setter> </Style>
It is also important to set the editor's DefaultStyleKey property to its own type in its constructor in order to be able to provide it with a default style.
Public Sub New() MyBase.New() Me.DefaultStyleKey = GetType( RatingCellEditor ) End Sub
public RatingCellEditor() : base() { this.DefaultStyleKey = typeof( RatingCellEditor ); }
Although not required to edit using the RatingCellEditor, the CellContentTemplate is also defined in the example below to demonstrate how to create the "visualization" counterpart of the editor. |
<sldg:Column FieldName="Rating"> <sldg:Column.CellEditorTemplate> <DataTemplate> <ContentControl x:Name="ratingControl"> <ContentControl.ContentTemplate> <DataTemplate> <local:RatingCellEditor Content="{Binding Path=Content, ElementName=ratingControl, Mode=TwoWay}" /> </DataTemplate> </ContentControl.ContentTemplate> </ContentControl> </DataTemplate> </sldg:Column.CellEditorTemplate> </sldg:Column>